/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.foxinline.util;

import br.com.foxinline.enums.Caracterizacao;
import br.com.foxinline.enums.Cobertura;
import br.com.foxinline.enums.DominioTerra;
import br.com.foxinline.enums.EstadoConservacao;
import br.com.foxinline.enums.Estrutura;
import br.com.foxinline.enums.Fachada;
import br.com.foxinline.enums.FatorLocalizacao;
import br.com.foxinline.enums.Forro;
import br.com.foxinline.enums.InstSanitaria;
import br.com.foxinline.enums.InstalacoesEletricas;
import br.com.foxinline.enums.Ocupacao;
import br.com.foxinline.enums.Patrimonio;
import br.com.foxinline.enums.Pedologia;
import br.com.foxinline.enums.Piso;
import br.com.foxinline.enums.Posicao;
import br.com.foxinline.enums.RevExterno;
import br.com.foxinline.enums.SaneamentoBasico;
import br.com.foxinline.enums.SistemaAgua;
import br.com.foxinline.enums.SituacaoImovel;
import br.com.foxinline.enums.SituacaoTerreno;
import br.com.foxinline.enums.TipoConstrucao;
import br.com.foxinline.enums.TipoDocumentoImovel;
import br.com.foxinline.enums.TipoPavimentacao;
import br.com.foxinline.enums.TipoPropriedade;
import br.com.foxinline.enums.TipoTitulo;
import br.com.foxinline.enums.Topografia;
import br.com.foxinline.enums.UsoImovel;
import br.com.foxinline.enums.Utilizacao;
import br.com.foxinline.enums.Vinculo;
import br.com.foxinline.modelo.Anexo;
import br.com.foxinline.modelo.Bairro;
import br.com.foxinline.modelo.Endereco;
import br.com.foxinline.modelo.Imovel;
import br.com.foxinline.modelo.Proprietario;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author nayra
 */
public class ImovelMerge {

    private Imovel imInclusao;
    private Imovel imAlteracao;
    private List<Campo<?>> campos;
    private List<Campo<?>> cEndereco;
    private List<Campo<?>> cEnderecoCorresp;
    private Endereco enderecoIncluido;
    private Endereco endCorrespIncluido;
    private List<Campo<Anexo>> anexosIncluidos;
    private List<Campo<Proprietario>> proprietariosIncluidos;
    private List<ProprietarioMerge> proprietariosMerge;
    private Boolean usarEnderecoIncluido;
    private Boolean usarEndCorrespIncluido;
    private Boolean propMergeDisplay;
    

    public ImovelMerge(Imovel im1, Imovel im2) {
        this.imInclusao = im1;
        this.imAlteracao = im2;

        this.campos = new ArrayList<Campo<?>>();
        this.anexosIncluidos = new ArrayList<Campo<Anexo>>();
        this.proprietariosIncluidos = new ArrayList<Campo<Proprietario>>();
        this.proprietariosMerge = new ArrayList<ProprietarioMerge>();
        this.usarEnderecoIncluido = true;
        this.usarEndCorrespIncluido = true;
        this.propMergeDisplay = false;

        //Boolean
        addCampo(new Campo<Boolean>("Isento TSU", "insetoTsu", imInclusao.getIsentoTsu(), imAlteracao.getIsentoTsu(), Boolean.class), this.campos);
        addCampo(new Campo<Boolean>("Ilum. Pública", "iluminacaoPublica", imInclusao.getIluminacaoPublica(), imAlteracao.getIluminacaoPublica(), Boolean.class), this.campos);
        addCampo(new Campo<Boolean>("Limp. Pública", "limpezaPublica", imInclusao.getLimpezaPublica(), imAlteracao.getLimpezaPublica(), Boolean.class), this.campos);
        addCampo(new Campo<Boolean>("Coleta de Lixo", "coletaLixo", imInclusao.getColetaLixo(), imAlteracao.getColetaLixo(), Boolean.class), this.campos);
        addCampo(new Campo<Boolean>("Calçamento", "calcamento", imInclusao.getCalcamento(), imAlteracao.getCalcamento(), Boolean.class), this.campos);
        addCampo(new Campo<Boolean>("Paga IPTU", "pagaIptu", imInclusao.getPagaIptu(), imAlteracao.getPagaIptu(), Boolean.class), this.campos);
        addCampo(new Campo<Boolean>("Reg. Imóvel", "regImovel", imInclusao.getRegImovel(), imAlteracao.getRegImovel(), Boolean.class), this.campos);
        addCampo(new Campo<Boolean>("RIP", "ripNomeCadastrado", imInclusao.getRipNomeCadastrado(), imAlteracao.getRipNomeCadastrado(), Boolean.class), this.campos);
        addCampo(new Campo<Boolean>("Titular Falecido", "titularFalecido", imInclusao.getTitularFalecido(), imAlteracao.getTitularFalecido(), Boolean.class), this.campos);
        addCampo(new Campo<Boolean>("Rec. Outro Ben. do Gov.", "recebeOutroBeneficioGovernoFederal", imInclusao.getRecebeOutroBeneficioGovernoFederal(), imAlteracao.getRecebeOutroBeneficioGovernoFederal(), Boolean.class), this.campos);
        addCampo(new Campo<Boolean>("Pes. com Neces. Esp.", "pessoasComNecessidadesEspeciais", imInclusao.getPessoasComNecessidadesEspeciais(), imAlteracao.getPessoasComNecessidadesEspeciais(), Boolean.class), this.campos);
        addCampo(new Campo<Boolean>("Pes. com Morb.", "pessoasComMorbidade", imInclusao.getPessoasComMorbidade(), imAlteracao.getPessoasComMorbidade(), Boolean.class), this.campos);

        //String
        addCampo(new Campo<String>("Fator de Localização", "fatorLocalizacao", imInclusao.getFatorLocalizacao(), imAlteracao.getFatorLocalizacao(), String.class), this.campos);
        addCampo(new Campo<String>("Frente", "frente", imInclusao.getFrente(), imAlteracao.getFrente(), String.class), this.campos);
        addCampo(new Campo<String>("Frente Rua", "frenteRua", imInclusao.getFrenteRua(), imAlteracao.getFrenteRua(), String.class), this.campos);
        addCampo(new Campo<String>("Fundo", "fundo", imInclusao.getFundo(), imAlteracao.getFundo(), String.class), this.campos);
        addCampo(new Campo<String>("Fundo Rua", "fundoRua", imInclusao.getFundoRua(), imAlteracao.getFundoRua(), String.class), this.campos);
        addCampo(new Campo<String>("Lado Esquerdo", "ladoEsquerdo", imInclusao.getLadoEsquerdo(), imAlteracao.getLadoEsquerdo(), String.class), this.campos);
        addCampo(new Campo<String>("Lado Esquerdo Rua", "ladoEsquerdoRua", imInclusao.getLadoEsquerdoRua(), imAlteracao.getLadoEsquerdoRua(), String.class), this.campos);
        addCampo(new Campo<String>("Lado Direito", "ladoDireito", imInclusao.getLadoDireito(), imAlteracao.getLadoDireito(), String.class), this.campos);
        addCampo(new Campo<String>("Lado Direito Rua", "ladoDireitoRua", imInclusao.getLadoDireitoRua(), imAlteracao.getLadoDireitoRua(), String.class), this.campos);
        addCampo(new Campo<String>("RIP", "rip", imInclusao.getRip(), imAlteracao.getRip(), String.class), this.campos);
        addCampo(new Campo<String>("Observação", "obs", imInclusao.getObs(), imAlteracao.getObs(), String.class), this.campos);
//        addCampo(new Campo<String>("Grupo Atualização", "groupUpdate", imInclusao.getGroupUpdate(), imAlteracao.getGroupUpdate(), String.class), this.campos);
        addCampo(new Campo<String>("Pes. Com Morb. Tipo", "pessoasComMorbidadeTipo", imInclusao.getPessoasComMorbidadeTipo(), imAlteracao.getPessoasComMorbidadeTipo(), String.class), this.campos);

        //BigDecimal
        addCampo(new Campo<BigDecimal>("Frente Medindo", "frenteMedindo", imInclusao.getFrenteMedindo(), imAlteracao.getFrenteMedindo(), BigDecimal.class), this.campos);
        addCampo(new Campo<BigDecimal>("Fundo Medindo", "fundoMedindo", imInclusao.getFundoMedindo(), imAlteracao.getFundoMedindo(), BigDecimal.class), this.campos);
        addCampo(new Campo<BigDecimal>("Lado Esq. Medindo", "ladoEsquerdoMedindo", imInclusao.getLadoEsquerdoMedindo(), imAlteracao.getLadoEsquerdoMedindo(), BigDecimal.class), this.campos);
        addCampo(new Campo<BigDecimal>("Lado Direito Medindo", "ladoDireitoMedindo", imInclusao.getLadoDireitoMedindo(), imAlteracao.getLadoDireitoMedindo(), BigDecimal.class), this.campos);

        //Integer
        addCampo(new Campo<Integer>("Qtd Pes. c/ Neces. Esp.", "pessoasComNecessidadesEspeciaisQuantidade", imInclusao.getPessoasComNecessidadesEspeciaisQuantidade(), imAlteracao.getPessoasComNecessidadesEspeciaisQuantidade(), Integer.class), this.campos);

        //Enum
        addCampo(new Campo<FatorLocalizacao>("Localização", "localizacao",
                imInclusao.getLocalizacao(), imAlteracao.getLocalizacao(), FatorLocalizacao.class), this.campos);
        addCampo(new Campo<Cobertura>("Cobertura", "cobertura",
                imInclusao.getCobertura(), imAlteracao.getCobertura(), Cobertura.class), this.campos);
        addCampo(new Campo<EstadoConservacao>("Estado Conservação", "estadoConservacao",
                imInclusao.getEstadoConservacao(), imAlteracao.getEstadoConservacao(), EstadoConservacao.class), this.campos);
        addCampo(new Campo<Estrutura>("Estrutura", "estrutura",
                imInclusao.getEstrutura(), imAlteracao.getEstrutura(), Estrutura.class), this.campos);
        addCampo(new Campo<Fachada>("Fachada", "fachada",
                imInclusao.getFachada(), imAlteracao.getFachada(), Fachada.class), this.campos);
        addCampo(new Campo<Forro>("Forro", "forro",
                imInclusao.getForro(), imAlteracao.getForro(), Forro.class), this.campos);
        addCampo(new Campo<InstalacoesEletricas>("Inst. Elétricas", "instalacoesEletricas",
                imInclusao.getInstalacoesEletricas(), imAlteracao.getInstalacoesEletricas(), InstalacoesEletricas.class), this.campos);
        addCampo(new Campo<InstSanitaria>("Inst. Sanitárias", "instSanitaria",
                imInclusao.getInstSanitaria(), imAlteracao.getInstSanitaria(), InstSanitaria.class), this.campos);
        addCampo(new Campo<Ocupacao>("Ocupação", "ocupacao",
                imInclusao.getOcupacao(), imAlteracao.getOcupacao(), Ocupacao.class), this.campos);
        addCampo(new Campo<Patrimonio>("Patrimônio", "patrimonio",
                imInclusao.getPatrimonio(), imAlteracao.getPatrimonio(), Patrimonio.class), this.campos);
        addCampo(new Campo<Pedologia>("Pedologia", "pedologia",
                imInclusao.getPedologia(), imAlteracao.getPedologia(), Pedologia.class), this.campos);
        addCampo(new Campo<Piso>("Piso", "piso",
                imInclusao.getPiso(), imAlteracao.getPiso(), Piso.class), this.campos);
        addCampo(new Campo<Posicao>("Posição", "posicao",
                imInclusao.getPosicao(), imAlteracao.getPosicao(), Posicao.class), this.campos);
        addCampo(new Campo<RevExterno>("Revest. Externo", "revExterno",
                imInclusao.getRevExterno(), imAlteracao.getRevExterno(), RevExterno.class), this.campos);
        addCampo(new Campo<SituacaoTerreno>("Situação Terreno", "situacaoTerreno",
                imInclusao.getSituacaoTerreno(), imAlteracao.getSituacaoTerreno(), SituacaoTerreno.class), this.campos);
        addCampo(new Campo<TipoConstrucao>("Tipo Construção", "tipoConstrucao",
                imInclusao.getTipoConstrucao(), imAlteracao.getTipoConstrucao(), TipoConstrucao.class), this.campos);
        addCampo(new Campo<Topografia>("Topografia", "topografia",
                imInclusao.getTopografia(), imAlteracao.getTopografia(), Topografia.class), this.campos);
        addCampo(new Campo<UsoImovel>("Uso Imóvel", "usoImovel",
                imInclusao.getUsoImovel(), imAlteracao.getUsoImovel(), UsoImovel.class), this.campos);
        addCampo(new Campo<Utilizacao>("Utilização", "utilizacao",
                imInclusao.getUtilizacao(), imAlteracao.getUtilizacao(), Utilizacao.class), this.campos);
        addCampo(new Campo<Caracterizacao>("Caracterização", "caracterizacao",
                imInclusao.getCaracterizacao(), imAlteracao.getCaracterizacao(), Caracterizacao.class), this.campos);
        addCampo(new Campo<TipoDocumentoImovel>("Tipo Doc. Imóvel", "tipoDocumentoImovel",
                imInclusao.getTipoDocumentoImovel(), imAlteracao.getTipoDocumentoImovel(), TipoDocumentoImovel.class), this.campos);
        addCampo(new Campo<Vinculo>("Vinc. Titular Rip", "vinculoTitularRip",
                imInclusao.getVinculoTitularRip(), imAlteracao.getVinculoTitularRip(), Vinculo.class), this.campos);
        addCampo(new Campo<DominioTerra>("Domínio Terra", "dominioTerra",
                imInclusao.getDominioTerra(), imAlteracao.getDominioTerra(), DominioTerra.class), this.campos);
        addCampo(new Campo<SituacaoImovel>("Situação Imóvel", "situacaoImovel",
                imInclusao.getSituacaoImovel(), imAlteracao.getSituacaoImovel(), SituacaoImovel.class), this.campos);
        addCampo(new Campo<TipoPropriedade>("Tipo Propriedade", "tipoPropriedade",
                imInclusao.getTipoPropriedade(), imAlteracao.getTipoPropriedade(), TipoPropriedade.class), this.campos);
        addCampo(new Campo<TipoTitulo>("Tipo Título", "tipoTitulo",
                imInclusao.getTipoTitulo(), imAlteracao.getTipoTitulo(), TipoTitulo.class), this.campos);
        addCampo(new Campo<TipoPavimentacao>("Tipo Pavimentação", "tipoPavimentacao",
                imInclusao.getTipoPavimentacao(), imAlteracao.getTipoPavimentacao(), TipoPavimentacao.class), this.campos);
        addCampo(new Campo<SistemaAgua>("Sistema Água", "sistemaAgua",
                imInclusao.getSistemaAgua(), imAlteracao.getSistemaAgua(), SistemaAgua.class), this.campos);
        addCampo(new Campo<SaneamentoBasico>("Saneamento Básico", "saneamentoBasico",
                imInclusao.getSaneamentoBasico(), imAlteracao.getSaneamentoBasico(), SaneamentoBasico.class), this.campos);

        //Endereco Imovel
        Endereco endImovelInc = this.imInclusao.getEnderecoImovel();
        Endereco endImovelAlt = this.imAlteracao.getEnderecoImovel();
        if (endImovelAlt != null) {
            if (endImovelInc == null || (endImovelInc != null && endImovelInc.equals(new Endereco()))) {
                this.enderecoIncluido = endImovelAlt;
            } else {
                this.cEndereco = new ArrayList<Campo<?>>();
                addCampo(new Campo<String>("Logradouro", "logradouro", endImovelInc.getLogradouro(), endImovelAlt.getLogradouro(), String.class), cEndereco);
                addCampo(new Campo<String>("Número", "numero", endImovelInc.getNumero(), endImovelAlt.getNumero(), String.class), cEndereco);
                addCampo(new Campo<String>("Complemento", "compl", endImovelInc.getCompl(), endImovelAlt.getCompl(), String.class), cEndereco);
                addCampo(new Campo<Bairro>("Bairro", "bairroDne", endImovelInc.getBairroDne(), endImovelAlt.getBairroDne(), Bairro.class), cEndereco);
                addCampo(new Campo<String>("Município", "municipio", endImovelInc.getMunicipio(), endImovelAlt.getMunicipio(), String.class), cEndereco);
                addCampo(new Campo<String>("CEP", "cep", endImovelInc.getCep(), endImovelAlt.getCep(), String.class), cEndereco);
            }
        }

        //Endereco Correspondencia Imovel
        Endereco endCInc = this.imInclusao.getEnderecoCorrespondencia();
        Endereco endCAlt = this.imAlteracao.getEnderecoCorrespondencia();
        if (endCAlt != null) {
            if (endCInc == null || (endCInc != null && endCInc.equals(new Endereco()))) {
                this.endCorrespIncluido = endCAlt;
            } else {
                this.cEnderecoCorresp = new ArrayList<Campo<?>>();
                addCampo(new Campo<String>("Logradouro", "logradouro", endCInc.getLogradouro(), endCAlt.getLogradouro(), String.class), cEnderecoCorresp);
                addCampo(new Campo<String>("Número", "numero", endCInc.getNumero(), endCAlt.getNumero(), String.class), cEnderecoCorresp);
                addCampo(new Campo<String>("Complemento", "compl", endCInc.getCompl(), endCAlt.getCompl(), String.class), cEnderecoCorresp);
                addCampo(new Campo<Bairro>("Bairro", "bairroDne", endCInc.getBairroDne(), endCAlt.getBairroDne(), Bairro.class), cEnderecoCorresp);
                addCampo(new Campo<String>("Município", "municipio", endCInc.getMunicipio(), endCAlt.getMunicipio(), String.class), cEnderecoCorresp);
                addCampo(new Campo<String>("CEP", "cep", endCInc.getCep(), endCAlt.getCep(), String.class), cEnderecoCorresp);
            }
        }

        //Anexos
        if (this.imAlteracao.getAnnex() != null) {
            for (Anexo anexo : this.imAlteracao.getAnnex()) {
                this.anexosIncluidos.add(new Campo(anexo, Anexo.class, true));
            }
        }

        //Proprietarios
        verificaProprietarios();
        
        for (ProprietarioMerge pm : this.proprietariosMerge) {
            if(pm.getTemDiferenca()){
                this.propMergeDisplay = true;
                break;
            }
        }
    }

    private void addCampo(Campo cp, List<Campo<?>> list) {
        if (cp.getDiferente()) {
            list.add(cp);
        }
    }

    private void verificaProprietarios() {
        for (Proprietario pAlt : this.imAlteracao.getProprietarios()) {
            if (isEmpty(pAlt.getCpf()) && isEmpty(pAlt.getCnpj())) {
                this.proprietariosIncluidos.add(new Campo<Proprietario>(pAlt, Proprietario.class, true));
            } else {
                String documento = isEmpty(pAlt.getCpf()) ? pAlt.getCnpj() : pAlt.getCpf();
                boolean cadastrado = false;

                for (Proprietario pInc : this.imInclusao.getProprietarios()) {
                    if (isEmpty(pInc.getCpf()) && isEmpty(pInc.getCnpj())) {
                        cadastrado = false;
                        continue;
                    } else {
                        if ((!isEmpty(pInc.getCpf()) && documento.equals(pInc.getCpf()))
                                || (!isEmpty(pInc.getCnpj()) && documento.equals(pInc.getCnpj()))) {
                            cadastrado = true;
                            this.proprietariosMerge.add(new ProprietarioMerge(pInc, pAlt, false));
                            break;
                        }
                    }
                }

                if (!cadastrado) {
                    this.proprietariosIncluidos.add(new Campo<Proprietario>(pAlt, Proprietario.class, true));
                }

            }
        }
    }

    public boolean isEmpty(CharSequence cs) {
        return cs == null || cs.length() == 0;
    }

    public Imovel getImInclusao() {
        return imInclusao;
    }

    public void setImInclusao(Imovel imInc) {
        this.imInclusao = imInc;
    }

    public Imovel getImAlteracao() {
        return imAlteracao;
    }

    public void setImAlteracao(Imovel imAlt) {
        this.imAlteracao = imAlt;
    }

    public List<Campo<?>> getCampos() {
        return campos;
    }

    public void setCampos(List<Campo<?>> campos) {
        this.campos = campos;
    }

    public List<Campo<?>> getcEndereco() {
        return cEndereco;
    }

    public void setcEndereco(List<Campo<?>> cEnd) {
        this.cEndereco = cEnd;
    }

    public List<Campo<?>> getcEnderecoCorresp() {
        return cEnderecoCorresp;
    }

    public void setcEnderecoCorresp(List<Campo<?>> cEndCorresp) {
        this.cEnderecoCorresp = cEndCorresp;
    }

    public List<Campo<Anexo>> getAnexosIncluidos() {
        return anexosIncluidos;
    }

    public void setAnexosIncluidos(List<Campo<Anexo>> aneAlt) {
        this.anexosIncluidos = aneAlt;
    }

    public List<Campo<Proprietario>> getProprietariosIncluidos() {
        return proprietariosIncluidos;
    }

    public void setProprietariosIncluidos(List<Campo<Proprietario>> propAlt) {
        this.proprietariosIncluidos = propAlt;
    }

    public List<ProprietarioMerge> getProprietariosMerge() {
        return proprietariosMerge;
    }

    public void setProprietariosMerge(List<ProprietarioMerge> props) {
        this.proprietariosMerge = props;
    }

    public Endereco getEnderecoIncluido() {
        return enderecoIncluido;
    }

    public void setEndAlt(Endereco endAlt) {
        this.enderecoIncluido = endAlt;
    }

    public Endereco getEndCorrespIncluido() {
        return endCorrespIncluido;
    }

    public void setEndCorrespIncluido(Endereco endCorrespAlt) {
        this.endCorrespIncluido = endCorrespAlt;
    }

    public Boolean getUsarEnderecoIncluido() {
        return usarEnderecoIncluido;
    }

    public void setUsarEnderecoIncluido(Boolean usarEndAlt) {
        this.usarEnderecoIncluido = usarEndAlt;
    }

    public Boolean getUsarEndCorrespIncluido() {
        return usarEndCorrespIncluido;
    }

    public void setUsarEndCorrespIncluido(Boolean usarEndCorrespAlt) {
        this.usarEndCorrespIncluido = usarEndCorrespAlt;
    }

    public Boolean getPropMergeDisplay() {
        return propMergeDisplay;
    }

    public void setPropMergeDisplay(Boolean propMergeDisplay) {
        this.propMergeDisplay = propMergeDisplay;
    }
    
}
